home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / glchess / chess / san.pyc (.txt) < prev   
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  11.5 KB  |  399 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''
  5. '''
  6. __author__ = 'Robert Ancell <bob27@users.sourceforge.net>'
  7. __license__ = 'GNU General Public License Version 2'
  8. __copyright__ = 'Copyright 2005-2006  Robert Ancell'
  9. __all__ = [
  10.     'SANConverter']
  11. SAN_TAKE = 'x'
  12. SAN_CASTLE_SHORT = 'O-O'
  13. SAN_CASTLE_LONG = 'O-O-O'
  14. RANKS = 'abcdefgh'
  15. FILES = '12345678'
  16. SAN_PROMOTE = '='
  17.  
  18. class Error(Exception):
  19.     '''
  20.     '''
  21.     pass
  22.  
  23.  
  24. class SANConverter:
  25.     '''
  26.     
  27.     Define file and rank
  28.     '''
  29.     WHITE = 'White'
  30.     BLACK = 'Black'
  31.     PAWN = 'P'
  32.     KNIGHT = 'N'
  33.     BISHOP = 'B'
  34.     ROOK = 'R'
  35.     QUEEN = 'Q'
  36.     KING = 'K'
  37.     __pieceTypes = PAWN + KNIGHT + BISHOP + ROOK + QUEEN + KING
  38.     __promotionTypes = PAWN + KNIGHT + BISHOP + ROOK + QUEEN
  39.     CHECK = '+'
  40.     CHECKMATE = '#'
  41.     
  42.     def __init__(self):
  43.         '''Constructor'''
  44.         pass
  45.  
  46.     
  47.     def getPiece(self, location):
  48.         """Get a piece from the chess board.
  49.         
  50.         'location' is the location to get the piece from (string, e.g. 'a1', h8').
  51.         
  52.         Return a tuple containing (colour, type) or None if no piece at this location.
  53.         """
  54.         pass
  55.  
  56.     
  57.     def testMove(self, colour, start, end, promotionType, allowSuicide = False):
  58.         """Test if a move is valid.
  59.         
  60.         'colour' is the colour of the player making the move (self.WHITE or self.BLACK).
  61.         'start' is the board location to move from (string, e.g. 'a1', 'h8').
  62.         'end' is the board location to move to (string, e.g. 'a1', 'h8').
  63.         'promotionType' is the piece type to promote to (self.[PAWN|KNIGHT|BISHOP|ROOK|QUEEN]).
  64.         'allowSuicide' is a flag to show if the move should be disallowed (False) or
  65.                        allowed (True) if it would put the moving player into check.
  66.  
  67.         Return False if the move is dissallowed or
  68.                self.CHECK if the move puts the opponent into check or
  69.                self.CHECKMATE if the move puts the opponent into checkmate or
  70.                True if the move is allowed and does not put the opponent into check.
  71.         """
  72.         pass
  73.  
  74.     
  75.     def decode(self, colour, san):
  76.         """Decode a SAN move.
  77.         
  78.         'colour' is the colour of the player making the move (self.WHITE or self.BLACK).
  79.         'san' is the SAN description of the move (string).
  80.         
  81.         Returns the move this SAN describes in the form (start, end, promotionType).
  82.         'start' is the square to move from (string, e.g. 'a1', 'h8').
  83.         'end' is the square to move to (string, e.g. 'a1', 'h8').
  84.         'promotionType' is the piece to promote to (self.[KNIGHT|BISHOP|ROOK|QUEEN]).
  85.         If the move is invalid then an Error expection is raised.
  86.         """
  87.         copy = san[:]
  88.         expectedResult = True
  89.         if copy[-1] == self.CHECK or copy[-1] == self.CHECKMATE:
  90.             expectedResult = copy[-1]
  91.             copy = copy[:-1]
  92.         
  93.         promotionType = self.QUEEN
  94.         if copy[-2] == SAN_PROMOTE:
  95.             promotionType = copy[-1]
  96.             copy = copy[:-2]
  97.             if self._SANConverter__promotionTypes.find(promotionType) < 0:
  98.                 raise Error("Error decoding '%s', Invalid promotion type %s" % (repr(san), repr(promotionType)))
  99.             self._SANConverter__promotionTypes.find(promotionType) < 0
  100.         elif self._SANConverter__promotionTypes.find(copy[-1]) >= 0:
  101.             promotionType = copy[-1]
  102.             copy = copy[:-1]
  103.         
  104.         if colour is self.WHITE:
  105.             baseFile = '1'
  106.         else:
  107.             baseFile = '8'
  108.         if copy == SAN_CASTLE_SHORT:
  109.             return ('e' + baseFile, 'g' + baseFile, expectedResult, promotionType)
  110.         if copy == SAN_CASTLE_LONG:
  111.             return ('e' + baseFile, 'c' + baseFile, expectedResult, promotionType)
  112.         end = copy[-2:]
  113.         copy = copy[:-2]
  114.         if RANKS.find(end[0]) < 0 or FILES.find(end[1]) < 0:
  115.             raise Error("Error decoding '%s', Invalid destination type %s" % (repr(san), repr(end)))
  116.         FILES.find(end[1]) < 0
  117.         isTake = False
  118.         
  119.         try:
  120.             if copy[-1] == SAN_TAKE:
  121.                 isTake = True
  122.                 copy = copy[:-1]
  123.         except:
  124.             copy == SAN_CASTLE_LONG
  125.             copy == SAN_CASTLE_SHORT
  126.  
  127.         pieceType = self.PAWN
  128.         rank = None
  129.         if len(copy) > 0:
  130.             if RANKS.find(copy[0]) >= 0:
  131.                 rank = copy[0]
  132.                 copy = copy[1:]
  133.             
  134.         
  135.         file = None
  136.         if len(copy) > 0:
  137.             if FILES.find(copy[0]) >= 0:
  138.                 file = copy[0]
  139.                 copy = copy[1:]
  140.             
  141.         
  142.         if len(copy) != 0:
  143.             raise Error('Error decoding %s, Unexpected extra characters %s' % (repr(san), repr(end)))
  144.         len(copy) != 0
  145.         moveResult = None
  146.         move = None
  147.         if rank is not None and file is not None:
  148.             start = rank + file
  149.             moveResult = self.testMove(colour, start, end, promotionType = promotionType)
  150.             move = (start, end)
  151.         elif file is None:
  152.             fileRange = FILES
  153.         else:
  154.             fileRange = file
  155.         if rank is None:
  156.             rankRange = RANKS
  157.         else:
  158.             rankRange = rank
  159.         for file in fileRange:
  160.             for rank in rankRange:
  161.                 start = rank + file
  162.                 piece = self.getPiece(start)
  163.                 if piece is None:
  164.                     continue
  165.                 
  166.                 if piece[0] != colour or piece[1] != pieceType:
  167.                     continue
  168.                 
  169.                 result = self.testMove(colour, start, end, promotionType = promotionType)
  170.                 if result is False:
  171.                     continue
  172.                 
  173.                 if moveResult is not None:
  174.                     raise Error('Error decoding %s, Move is ambiguous, at least %s and %s are possible' % (repr(san), repr(move), repr([
  175.                         start,
  176.                         end])))
  177.                 moveResult is not None
  178.                 moveResult = result
  179.                 move = [
  180.                     start,
  181.                     end]
  182.             
  183.         
  184.         if moveResult is None:
  185.             raise Error('Error decoding %s, Not a valid move' % repr(san))
  186.         moveResult is None
  187.         return (move[0], move[1], expectedResult, promotionType)
  188.  
  189.     
  190.     def encode(self, start, end, isTake = False, promotionType = QUEEN):
  191.         """Convert glChess co-ordinate move to SAN notation.
  192.  
  193.         'start' is the square to move from (string, e.g. 'a1', 'h8').
  194.         'end' is the square to move to (string, e.g. 'a1', 'h8').
  195.         'promotionType' is the piece used for pawn promotion (if necessary).
  196.  
  197.         Return the move in SAN notation or None if unable to convert.
  198.         """
  199.         piece = self.getPiece(start)
  200.         if piece is None:
  201.             raise Error('Encode error, no piece to move at %s' % repr(start))
  202.         piece is None
  203.         (pieceColour, pieceType) = piece
  204.         if self.testMove(pieceColour, start, end, promotionType) is False:
  205.             raise Error('Encode error, move %s%s is invalid' % (start, end))
  206.         self.testMove(pieceColour, start, end, promotionType) is False
  207.         if pieceType is self.KING:
  208.             if pieceColour is self.WHITE:
  209.                 baseFile = '1'
  210.             else:
  211.                 baseFile = '8'
  212.             shortCastle = ('e' + baseFile, 'g' + baseFile)
  213.             longCastle = ('e' + baseFile, 'c' + baseFile)
  214.             san = None
  215.             if (start, end) == shortCastle:
  216.                 san = SAN_CASTLE_SHORT
  217.             elif (start, end) == longCastle:
  218.                 san = SAN_CASTLE_LONG
  219.             
  220.             if san is not None:
  221.                 result = self.testMove(pieceColour, start, end, promotionType = promotionType, allowSuicide = True)
  222.                 if result is self.CHECK:
  223.                     san += self.CHECK
  224.                 elif result is self.CHECKMATE:
  225.                     san += self.CHECKMATE
  226.                 
  227.                 return san
  228.         
  229.         file = '?'
  230.         rank = '?'
  231.         if pieceType is self.PAWN and isTake:
  232.             rank = start[0]
  233.         
  234.         result = self._SANConverter__isUnique(pieceColour, pieceType, rank + file, end, promotionType)
  235.         if result is None:
  236.             rank = start[0]
  237.             file = '?'
  238.             result = self._SANConverter__isUnique(pieceColour, pieceType, rank + '?', end, promotionType)
  239.             if result is None:
  240.                 rank = '?'
  241.                 file = start[1]
  242.                 result = self._SANConverter__isUnique(pieceColour, pieceType, '?' + file, end, promotionType)
  243.                 if result is None:
  244.                     result = self._SANConverter__isUnique(pieceColour, pieceType, rank + file, end, promotionType)
  245.                     if result is None:
  246.                         raise Error('Encode error, unable to find unique move for %s%s' % (start, end))
  247.                     result is None
  248.                 
  249.             
  250.         
  251.         san = ''
  252.         if pieceType is not self.PAWN:
  253.             san += pieceType
  254.         
  255.         if rank != '?':
  256.             san += rank
  257.         
  258.         if file != '?':
  259.             san += file
  260.         
  261.         if isTake:
  262.             san += SAN_TAKE
  263.         
  264.         san += end
  265.         if pieceColour is self.WHITE:
  266.             promotionFile = '8'
  267.         else:
  268.             promotionFile = '1'
  269.         if pieceType == self.PAWN and end[1] == promotionFile:
  270.             san += SAN_PROMOTE + promotionType
  271.         
  272.         if result is self.CHECK:
  273.             san += self.CHECK
  274.         elif result is self.CHECKMATE:
  275.             san += self.CHECKMATE
  276.         
  277.         return san
  278.  
  279.     
  280.     def __isUnique(self, colour, pieceType, start, end, promotionType = QUEEN):
  281.         """Test if a move is unique.
  282.     
  283.         'colour' is the piece colour being moved. (self.WHITE or self.BLACK).
  284.         'pieceType' is the type of the piece being moved (self.[PAWN|KNIGHT|BISHOP|ROOK|QUEEN|KING]).
  285.         'start' is the start location of the move (tuple (file, rank). rank and file can be None).
  286.         'end' is the end point of the move (tuple (file,rank)).
  287.         'promotionType' is the piece type to promote pawns to (self.[PAWN|KNIGHT|BISHOP|ROOK|QUEEN]).
  288.     
  289.         Return the result of self.testMove() if a unique move is found otherwise None.
  290.         """
  291.         lastResult = None
  292.         if start[0] == '?':
  293.             rankRange = RANKS
  294.         else:
  295.             rankRange = start[0]
  296.         if start[1] == '?':
  297.             fileRange = FILES
  298.         else:
  299.             fileRange = start[1]
  300.         for file in fileRange:
  301.             for rank in rankRange:
  302.                 p = self.getPiece(rank + file)
  303.                 if p is None:
  304.                     continue
  305.                 
  306.                 if p[1] != pieceType or p[0] != colour:
  307.                     continue
  308.                 
  309.                 result = self.testMove(colour, rank + file, end, promotionType = promotionType, allowSuicide = True)
  310.                 if result is not False:
  311.                     if lastResult != None:
  312.                         return None
  313.                     lastResult = result
  314.                     continue
  315.                 lastResult != None
  316.             
  317.         
  318.         return lastResult
  319.  
  320.  
  321. if __name__ == '__main__':
  322.     import chess_board
  323.     
  324.     class TestConverter(SANConverter):
  325.         '''
  326.         '''
  327.         __colourToSAN = {
  328.             chess_board.WHITE: SANConverter.WHITE,
  329.             chess_board.BLACK: SANConverter.BLACK }
  330.         __sanToColour = { }
  331.         for a, b in __colourToSAN.iteritems():
  332.             __sanToColour[b] = a
  333.         
  334.         __typeToSAN = {
  335.             chess_board.PAWN: SANConverter.PAWN,
  336.             chess_board.KNIGHT: SANConverter.KNIGHT,
  337.             chess_board.BISHOP: SANConverter.BISHOP,
  338.             chess_board.ROOK: SANConverter.ROOK,
  339.             chess_board.QUEEN: SANConverter.QUEEN,
  340.             chess_board.KING: SANConverter.KING }
  341.         __sanToType = { }
  342.         for a, b in __typeToSAN.iteritems():
  343.             __sanToType[b] = a
  344.         
  345.         __board = None
  346.         
  347.         def __init__(self, board):
  348.             self._TestConverter__board = board
  349.  
  350.         
  351.         def testEncode(self, start, end):
  352.             print str((start, end)) + ' => ' + str(self.encode(start, end))
  353.  
  354.         
  355.         def testDecode(self, colour, san):
  356.             
  357.             try:
  358.                 result = self.decode(colour, san)
  359.                 print san.ljust(7) + ' => ' + str(result)
  360.             except Error:
  361.                 e = None
  362.                 print san.ljust(7) + ' !! ' + str(e)
  363.  
  364.  
  365.         
  366.         def getPiece(self, file, rank):
  367.             '''Called by SANConverter'''
  368.             piece = self._TestConverter__board.getPiece((file, rank))
  369.             if piece is None:
  370.                 return None
  371.             return (self._TestConverter__colourToSAN[piece.getColour()], self._TestConverter__typeToSAN[piece.getType()])
  372.  
  373.         
  374.         def testMove(self, colour, start, end, promotionType, allowSuicide = False):
  375.             '''Called by SANConverter'''
  376.             moveResult = self._TestConverter__board.testMove(self._TestConverter__sanToColour[colour], (start, end), self._TestConverter__sanToType[promotionType], allowSuicide)
  377.             return {
  378.                 chess_board.MOVE_RESULT_ILLEGAL: False,
  379.                 chess_board.MOVE_RESULT_ALLOWED: True,
  380.                 chess_board.MOVE_RESULT_OPPONENT_CHECK: self.CHECK,
  381.                 chess_board.MOVE_RESULT_OPPONENT_CHECKMATE: self.CHECKMATE }[moveResult]
  382.  
  383.  
  384.     b = chess_board.ChessBoard()
  385.     c = TestConverter(b)
  386.     print b
  387.     c.testEncode((1, 1), (1, 2))
  388.     c.testEncode((1, 0), (2, 2))
  389.     c.testDecode(c.WHITE, 'c3')
  390.     c.testDecode(c.WHITE, 'Pc3')
  391.     c.testDecode(c.WHITE, 'c4')
  392.     c.testDecode(c.WHITE, 'Nc3')
  393.     c.testDecode(c.WHITE, 'Qd3')
  394.     c.testDecode(c.WHITE, 'Qd3=X')
  395.     c.testDecode(c.WHITE, 'x3')
  396.     c.testDecode(c.WHITE, 'ic3')
  397.     print b
  398.  
  399.